package com.easy.tool.utils.date;

import com.easy.tool.anno.BeanDes;
import com.easy.tool.anno.MethodDes;
import com.easy.tool.utils.bean.BeanUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author 高俊
 * @create 2021-08-2021/8/27-9:58
 */
@BeanDes(name = "日期时间工具类", des = "对时间进行一些常用操作")
public class DateUtils {

    /**
     * 格式化时间
     * @param date  需要格式化的时间
     * @param format    格式类型。例如：YYYY-MM-dd HH:mm:ss
     * @return String类型time
     */
    @MethodDes(des = "格式化时间",param = {"arg0-> date：需要格式化的时间","arg1-> format：格式类型。例如：YYYY-MM-dd HH:mm:ss"})
    public static String dateFormat(Date date , String format){
        SimpleDateFormat simpleFormat = new SimpleDateFormat(format);
        return simpleFormat.format(date);
    }

    /**
     * 字符串格式转时间对象
     * @param timeStr   字符串时间
     * @param format    格式
     * @return  时间对象
     */
    @MethodDes(des = "字符串格式转时间对象",param = {"arg0-> timeStr：字符串时间","arg1-> format：格式"})
    public static Date stringTimeToDate(String timeStr, String format){
        SimpleDateFormat simpleFormat = new SimpleDateFormat(format);
        Date date = null;
        try {
            date = simpleFormat.parse(timeStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }

    /**
     * 获取当前月份第一天/最后一天
     * @param type 0：第一天；1：最后一天
     * @return
     */
    @MethodDes(des = "获取当前月份第一天/最后一天",param = {"arg0-> type：0：第一天；1：最后一天"})
    public static Date getFirstDayOfMonth(Integer type){
        if (type == null){
            return null;
        }
        Calendar instance = Calendar.getInstance();
        if (type == 0){
            instance.set(Calendar.DAY_OF_MONTH,1);
        }else if (type == 1){
            int lastday = instance.getMaximum(Calendar.DAY_OF_MONTH);
            instance.set(Calendar.DATE,lastday);
        }
        return instance.getTime();
    }

    /**
     * 比较时间大小
     * @param date1 时间1
     * @param date2 时间2
     * @return  -1：date1<date2；1：date1 > date2
     */
    @MethodDes(des = "比较时间大小",param = {"arg0-> date1：时间1","arg1-> date2：时间2"})
    public static int dateCompare(Date date1,Date date2){
        long time = date1.getTime();
        long time1 = date2.getTime();
        if (time<time1){
            return -1;
        }
        return 1;
    }

    /**
     * 时间差
     * @param date1
     * @param date2
     * @return 毫秒值
     */
    @MethodDes(des = "时间差",param = {"arg0-> date1：时间1","arg1-> date2：时间2"})
    public static Long differTime(Date date1,Date date2){
        long time = date1.getTime();
        long time1 = date2.getTime();
        if (time<time1){
            return time1-time;
        }
        return time-time1;
    }

    /**
     * 获取指定月份第一天/最后一天
     * @param month 指定月份 1~12
     * @param type  0：第一天；1：最后一天
     * @return Date类型时间
     */
    @MethodDes(des = "获取指定月份第一天/最后一天",param = {"arg0-> month：指定月份 1~12","arg1-> type：0：第一天；1：最后一天"})
    public static Date appointDayOfMonth(int month,Integer type){
        Calendar instance = Calendar.getInstance();
        instance.set(Calendar.MONTH,month-1);
        if (type == 0){
            instance.set(Calendar.DAY_OF_MONTH, 1);
        }else if (type == 1){
            int lastday = instance.getMaximum(Calendar.DAY_OF_MONTH);
            instance.set(Calendar.DATE,lastday);
        }
        return instance.getTime();
    }

    /**
     * 从当前时间开始获取指定范围时间
     * @param days 范围天数
     * @param type 范围类型 0：向前；1：向后
     * @return
     */
    @MethodDes(des = "从当前时间开始获取指定范围时间(String)",explain = "返回String类型List",param = {"arg0-> days：范围天数","arg1-> type：范围类型 0：向前；1：向后"})
    public static List<String> getRangeDateStr(int days,int type){
        List<String> strList = new ArrayList<>();
        List<Date> list = getRangeDateSon(days, type);
        for (Date n : list) {
            strList.add(DateUtils.dateFormat(n,"yyyy-MM-dd"));
        }
        return strList;
    }


    /**
     * 从当前时间开始获取指定范围时间
     * @param days 范围天数
     * @param type 范围类型 0：向前；1：向后
     * @return
     */
    @MethodDes(des = "从当前时间开始获取指定范围时间(Date)",explain = "返回Date类型List",param = {"arg0-> days：范围天数","arg1-> type：范围类型 0：向前；1：向后"})
    public static List<Date> getRangeDateDat(int days,int type){
        List<Date> list = getRangeDateSon(days, type);
        return list;
    }

    private static List<Date> getRangeDateSon(int days,int type){
        List<Date> list = new ArrayList<>();
        long time = System.currentTimeMillis();
        for (int i = 1; i <= days; i++) {
            Calendar today = new GregorianCalendar(TimeZone.getTimeZone("GMT+8"));
            today.setTimeInMillis(time);
            if (type == 0) {
                today.add(Calendar.DAY_OF_MONTH, -i);
            }else {
                today.add(Calendar.DAY_OF_MONTH, i);
            }
            list.add(today.getTime());
        }
        return list;
    }

    /**
     * 获取指定范围时间
     * @param date 开始时间
     * @param days 范围天数
     * @param type 范围类型 0：向前；1：向后
     * @return
     */
    @MethodDes(des = "获取指定范围时间(Date)",explain = "返回Date类型List",param = {"arg0-> date：开始时间","arg1-> days：范围天数","arg3-> type：范围类型 0：向前；1：向后"})
    public static List<Date> getTowDateList(Date date,int days,int type){
        List<Date> list = new ArrayList<>();
        if (date == null){
            date = new Date();
        }

        for (int i = 1; i <= days; i++) {
            Calendar today = new GregorianCalendar(TimeZone.getTimeZone("GMT+8"));
            today.setTime(date);
            if (type == 0) {
                today.add(Calendar.DAY_OF_MONTH, -i);
            }else {
                today.add(Calendar.DAY_OF_MONTH, i);
            }
            list.add(today.getTime());
        }
        return list;
    }


    /**
     * 从指定日期开始，查询向前或向后指定天数
     * @param date date类型时间
     * @param day  位移天数
     * @param type -1：向前；1：向后
     * @return
     */
    @MethodDes(des = "查询向前指定天数",param = {"arg0-> date：Date类型时间","arg1-> day：天数","arg1-> type：-1：向前；1：向后"})
    public static String getMoveDays(Date date,int day,int type){
        Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT+8"));
        calendar.setTime(date);
        return getMoveDaysSon(day,calendar,type);
    }
    /**
     * 从指定日期开始，查询向前或向后指定天数
     * @param date date类型时间
     * @param day  位移天数
     * @param type -1：向前；1：向后
     * @return
     */
    @MethodDes(des = "从指定日期开始，查询向前或向后指定天数",param = {"arg0-> date：字符串类型时间","arg1-> day：天数","arg1-> type：-1：向前；1：向后"})
    public static String getMoveDays(String date,int day,int type){
        long time = stringTimeToDate(date, "yyyy-MM-dd").getTime();
        Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT+8"));
        calendar.setTimeInMillis(time);
        return getMoveDaysSon(day,calendar,type);
    }

    private static String getMoveDaysSon(int day,Calendar calendar,int type){

        if (type == -1){
            calendar.add(Calendar.DAY_OF_MONTH, day*type);
        } else if (type == 1) {
            calendar.add(Calendar.DAY_OF_MONTH, day*type);
        }
        return DateUtils.dateFormat(calendar.getTime(),"yyyy-MM-dd");
    }




    /**
     * 查询向后指定天数
     * @param day
     * @return
     */
    @MethodDes(des = "查询向后指定天数",param = {"arg0-> day：天数"})
    public static String getAfterDays(int day){
        long time = System.currentTimeMillis();
        Calendar today = new GregorianCalendar(TimeZone.getTimeZone("GMT+8"));
        today.setTimeInMillis(time);
        today.add(Calendar.DAY_OF_MONTH, day);
        return DateUtils.dateFormat(today.getTime(),"yyyy-MM-dd");
    }

    /**
     * 从指定日期开始，查询向后指定月份
     * @param date
     * @param month
     * @param type -1：向前；1：向后
     * @return
     */
    @MethodDes(des = "从指定日期开始，查询向后指定月份",param = {"arg0-> date：字符串类型日期","arg1-> day：位移几个月","arg2-> type：-1：向前；1：向后"})
    public static String getMoveMonth(String date,int month,int type){
        long time = stringTimeToDate(date, "yyyy-MM-dd").getTime();
        Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT+8"));
        calendar.setTimeInMillis(time);
        return getMoveDaysSon(month,calendar,type);
    }
    /**
     * 从指定日期开始，查询向后指定月份
     * @param date
     * @param month
     * @param type -1：向前；1：向后
     * @return
     */
    @MethodDes(des = "从指定日期开始，查询向前，向后指定月份",param = {"arg0-> date：Date类型日期","arg1-> day：位移几个月","arg2-> type：-1：向前；1：向后"})
    public static String getMoveMonth(Date date,int month,int type){
        Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT+8"));
        calendar.setTime(date);
        return getMoveMonthSon(month,calendar,type);
    }
    private static String getMoveMonthSon(int month,Calendar calendar,int type){
        if (type == -1){
            calendar.add(Calendar.MONTH,month*type);
        } else if (type == 1) {
            calendar.add(Calendar.MONTH,month*type);
        }
        return DateUtils.dateFormat(calendar.getTime(),"yyyy-MM-dd");
    }

    /**
     * 从指定日期开始，查询向后指定年份
     * @param date Date类型日期
     * @param year 位移几年
     * @param type -1：向前；1：向后
     * @return
     */
    @MethodDes(des = "查询向前，向后指定年份",param = {"arg0-> date：Date类型日期","arg1-> day：位移几年","arg2-> type：-1：向前；1：向后"})
    public static String getMoveYear(Date date,int year,int type){
        Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT+8"));
        calendar.setTime(date);
        return getMoveYearSon(year,calendar,type);
    }
    /**
     * 从指定日期开始，查询向后指定年份
     * @param date 字符串类型日期
     * @param year 位移几年
     * @param type -1：向前；1：向后
     * @return
     */
    @MethodDes(des = "查询向前，向后指定年份",param = {"arg0-> date：字符串类型日期","arg1-> day：位移几年","arg2-> type：-1：向前；1：向后"})
    public static String getMoveYear(String date,int year,int type){
        long time = stringTimeToDate(date, "yyyy-MM-dd").getTime();
        Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT+8"));
        calendar.setTimeInMillis(time);
        return getMoveYearSon(year,calendar,type);
    }
    private static String getMoveYearSon(int year,Calendar calendar,int type){
        if (type == -1){
            calendar.add(Calendar.YEAR,year*type);
        } else if (type == 1) {
            calendar.add(Calendar.YEAR,year*type);
        }
        return DateUtils.dateFormat(calendar.getTime(),"yyyy-MM-dd");
    }

    /**
     * 根据ms计算天数
     * @param ms ms数
     * @return
     */
    @MethodDes(des = "根据ms计算天数",param = {"arg0-> date：字符串类型日期"})
    public static long computedByMs(long ms){
        long day = ms / (1000 * 60 * 60 * 24);
        return day;
    }


}
